package org.hrqing.chess.frame;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.hrqing.chess.util.ImageUtils;

import javax.swing.*;
import java.awt.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author Hrqing
 */
@Getter
@Setter
@Slf4j
public class ChessLabel extends JLabel {

    public enum Purpose {
        ROCK(Map.of(Color.RED, "车", Color.BLACK, "车"), Map.of(Color.RED, "俥", Color.BLACK, "車")),
        KNIGHT(Map.of(Color.RED, "马", Color.BLACK, "马"), Map.of(Color.RED, "傌", Color.BLACK, "馬")),
        BISHOP(Map.of(Color.RED, "相", Color.BLACK, "象"), Map.of(Color.RED, "相", Color.BLACK, "象")),
        GUARD(Map.of(Color.RED, "士", Color.BLACK, "士"), Map.of(Color.RED, "仕", Color.BLACK, "士")),
        KING(Map.of(Color.RED, "帅", Color.BLACK, "将"), Map.of(Color.RED, "帥", Color.BLACK, "将")),
        CANNON(Map.of(Color.RED, "炮", Color.BLACK, "炮"), Map.of(Color.RED, "炮", Color.BLACK, "砲")),
        PAWN(Map.of(Color.RED, "兵", Color.BLACK, "卒"), Map.of(Color.RED, "兵", Color.BLACK, "卒")),
        ;
        @Getter
        private final Map<Color, String> simple;
        @Getter
        private final Map<Color, String> cname;

        Purpose(Map<Color, String> simple, Map<Color, String> cname) {
            this.simple = simple;
            this.cname = cname;
        }
    }

    public enum Color {
        RED("红方"),
        BLACK("黑方"),
        ;
        @Getter
        private final String simple;

        Color(String simple) {
            this.simple = simple;
        }
    }

    @Getter
    @Setter
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Piece implements Serializable {
        private Color color;
        private Purpose purpose;
        private String sign;
        private String image;
        private Integer x;
        private Integer y;
        private Integer top;
        private Integer left;

        public Piece(Color color, Purpose purpose, String sign, Integer x, Integer y) {
            this.color = color;
            this.purpose = purpose;
            this.sign = sign;
            this.x = x;
            this.y = y;
        }

        public String getId() {
            return x.toString() + "-" + y.toString();
        }
    }

    public static final List<Piece> PIECES = List.of(
            new Piece(Color.BLACK, Purpose.ROCK, "r", "image/black_rock.png", 1, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KNIGHT, "n", "image/black_knight.png", 2, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.BISHOP, "b", "image/black_bishop.png", 3, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.GUARD, "a", "image/black_guard.png", 4, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KING, "k", "image/black_king.png", 5, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.GUARD, "a", "image/black_guard.png", 6, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.BISHOP, "b", "image/black_bishop.png", 7, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KNIGHT, "n", "image/black_knight.png", 8, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.ROCK, "r", "image/black_rock.png", 9, 1, -5, -18),

            new Piece(Color.BLACK, Purpose.CANNON, "c", "image/black_cannon.png", 2, 3, -5, -18),
            new Piece(Color.BLACK, Purpose.CANNON, "c", "image/black_cannon.png", 8, 3, -5, -18),

            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/black_pawn.png", 1, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/black_pawn.png", 3, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/black_pawn.png", 5, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/black_pawn.png", 7, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/black_pawn.png", 9, 4, -5, -18),

            new Piece(Color.RED, Purpose.PAWN, "P", "image/red_pawn.png", 1, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/red_pawn.png", 3, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/red_pawn.png", 5, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/red_pawn.png", 7, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/red_pawn.png", 9, 7, -5, -18),

            new Piece(Color.RED, Purpose.CANNON, "C", "image/red_cannon.png", 2, 8, -5, -18),
            new Piece(Color.RED, Purpose.CANNON, "C", "image/red_cannon.png", 8, 8, -5, -18),

            new Piece(Color.RED, Purpose.ROCK, "R", "image/red_rock.png", 1, 10, -5, -18),
            new Piece(Color.RED, Purpose.KNIGHT, "N", "image/red_knight.png", 2, 10, -5, -18),
            new Piece(Color.RED, Purpose.BISHOP, "B", "image/red_bishop.png", 3, 10, -5, -18),
            new Piece(Color.RED, Purpose.GUARD, "A", "image/red_guard.png", 4, 10, -5, -18),
            new Piece(Color.RED, Purpose.KING, "K", "image/red_king.png", 5, 10, -5, -18),
            new Piece(Color.RED, Purpose.GUARD, "A", "image/red_guard.png", 6, 10, -5, -18),
            new Piece(Color.RED, Purpose.BISHOP, "B", "image/red_bishop.png", 7, 10, -5, -18),
            new Piece(Color.RED, Purpose.KNIGHT, "N", "image/red_knight.png", 8, 10, -5, -18),
            new Piece(Color.RED, Purpose.ROCK, "R", "image/red_rock.png", 9, 10, -5, -18)
    );

    public static final List<Piece> REVERSE_PIECES = List.of(
            new Piece(Color.BLACK, Purpose.ROCK, "r", "image/red_rock.png", 1, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KNIGHT, "n", "image/red_knight.png", 2, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.BISHOP, "b", "image/red_bishop.png", 3, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.GUARD, "a", "image/red_guard.png", 4, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KING, "k", "image/red_king.png", 5, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.GUARD, "a", "image/red_guard.png", 6, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.BISHOP, "b", "image/red_bishop.png", 7, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.KNIGHT, "n", "image/red_knight.png", 8, 1, -5, -18),
            new Piece(Color.BLACK, Purpose.ROCK, "r", "image/red_rock.png", 9, 1, -5, -18),

            new Piece(Color.BLACK, Purpose.CANNON, "c", "image/red_cannon.png", 2, 3, -5, -18),
            new Piece(Color.BLACK, Purpose.CANNON, "c", "image/red_cannon.png", 8, 3, -5, -18),

            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/red_pawn.png", 1, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/red_pawn.png", 3, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/red_pawn.png", 5, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/red_pawn.png", 7, 4, -5, -18),
            new Piece(Color.BLACK, Purpose.PAWN, "p", "image/red_pawn.png", 9, 4, -5, -18),

            new Piece(Color.RED, Purpose.PAWN, "P", "image/black_pawn.png", 1, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/black_pawn.png", 3, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/black_pawn.png", 5, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/black_pawn.png", 7, 7, -5, -18),
            new Piece(Color.RED, Purpose.PAWN, "P", "image/black_pawn.png", 9, 7, -5, -18),

            new Piece(Color.RED, Purpose.CANNON, "C", "image/black_cannon.png", 2, 8, -5, -18),
            new Piece(Color.RED, Purpose.CANNON, "C", "image/black_cannon.png", 8, 8, -5, -18),

            new Piece(Color.RED, Purpose.ROCK, "R", "image/black_rock.png", 1, 10, -5, -18),
            new Piece(Color.RED, Purpose.KNIGHT, "N", "image/black_knight.png", 2, 10, -5, -18),
            new Piece(Color.RED, Purpose.BISHOP, "B", "image/black_bishop.png", 3, 10, -5, -18),
            new Piece(Color.RED, Purpose.GUARD, "A", "image/black_guard.png", 4, 10, -5, -18),
            new Piece(Color.RED, Purpose.KING, "K", "image/black_king.png", 5, 10, -5, -18),
            new Piece(Color.RED, Purpose.GUARD, "A", "image/black_guard.png", 6, 10, -5, -18),
            new Piece(Color.RED, Purpose.BISHOP, "B", "image/black_bishop.png", 7, 10, -5, -18),
            new Piece(Color.RED, Purpose.KNIGHT, "N", "image/black_knight.png", 8, 10, -5, -18),
            new Piece(Color.RED, Purpose.ROCK, "R", "image/black_rock.png", 9, 10, -5, -18)
    );

    private String id;
    private Color color;
    private Purpose purpose;
    private String rule;
    private String sign;
    private Integer top = 0;
    private Integer left = 0;
    private boolean selected = false;

    public Color enemyColor() {
        return this.getColor().equals(Color.RED) ? Color.BLACK : Color.RED;
    }

    public static void restore(CenterBackgroundPanel panel) {
        log.info("initialization plate");
        log.info("{} plate", panel.getColor().equals(Color.RED) ? "positive" : "negative");
        restore(panel, panel.getColor().equals(Color.RED) ? PIECES : REVERSE_PIECES);
    }

    public static void restore(CenterBackgroundPanel panel, List<ChessLabel.Piece> pieces) {
        panel.removeAll();
        panel.repaint();
        for (ChessLabel.Piece piece : pieces) {
            Image image = panel.getColor().equals(Color.RED) ? ImageUtils.loadImage(piece.getImage()) : ImageUtils.loadReverseImage(piece.getImage());
            Image scaledImage = image.getScaledInstance(
                    76,
                    79,
                    Image.SCALE_SMOOTH
            );
            ImageIcon imageIcon = new ImageIcon(scaledImage);
            ChessLabel picLabel = new ChessLabel();
            picLabel.setIcon(imageIcon);
            picLabel.setId(piece.getId());
            picLabel.setColor(piece.getColor());
            picLabel.setPurpose(piece.getPurpose());
            picLabel.setSign(piece.getSign());
            picLabel.setTop(piece.getTop());
            picLabel.setLeft(piece.getLeft());

            // 配置约束对象
            log.info("insert chess {}, {}", piece.x, piece.y);
            insert(panel, picLabel, piece.x, piece.y);
        }
        panel.revalidate();
    }

    public static void insert(JPanel panel, ChessLabel picLabel, int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(picLabel.getTop() == null ? -5 : picLabel.getTop(),
                picLabel.getLeft() == null ? -18 : picLabel.getLeft(),
                0,
                0);
        // 添加组件到布局
        panel.add(picLabel, gbc);
    }

    public static void selected(JPanel panel, Color color) {
        Component[] components = panel.getComponents();
        for (Component component : components) {
            if (component instanceof ChessLabel chess) {
                chess.setSelected(false);
            }
        }
        for (Component component : components) {
            if (component instanceof ChessLabel chess) {
                if (chess.getColor().equals(color)) {
                    chess.setSelected(true);
                }
            }
        }
    }

    public static Piece piece(Color color, Purpose purpose) {
        Optional<Piece> first = PIECES.stream().filter(filter -> filter.getColor().equals(color) && filter.getPurpose().equals(purpose)).findFirst();
        return first.orElse(null);
    }

    public ChessLabel clone() {
        ChessLabel clone = new ChessLabel();
        clone.setId(id + "-clone");
        clone.setColor(color);
        clone.setTop(top);
        clone.setLeft(left);
        clone.setSelected(false);
        clone.setBounds(this.getBounds());
        clone.setIcon(this.getIcon());
        clone.setPurpose(purpose);
        clone.setSign(sign);
        return clone;
    }

}
